﻿#region Copyright © 2013 Paul Miller (Millz)
// All rights are reserved. Reproduction or transmission in whole or in part,
// any form or by any means, electronic, mechanical or otherwise, is prohibited
// without the prior written consent of the copyright owner.
// 
// Filename: Common.cs
// Date:     23/09/2013
// Author:   Paul Miller (Millz)
#endregion
using System;
using System.Linq;
using Insanity.Core;
using Insanity.Helpers;
using Insanity.Managers;
using Insanity.Settings;
using Styx;
using Styx.CommonBot;
using Styx.TreeSharp;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;

namespace Insanity.Specialisation
{
    static class Common
    {
        private static InsanitySettings Settings { get { return InsanitySettings.Instance; } }
        private static LocalPlayer Me { get { return StyxWoW.Me; } }

        public static Composite Combat()
        {
            return new PrioritySelector(
                
                // Racials
                Racials.UseRacials(),

                // Items
                Item.UseTrinkets(),
                HandlePotionOfTheJadeSerpent(),
                HandleEngineerGloves(),
                HandleUseHealthstones(),

                // General Abilities
                HandleLifeblood(),
                FearWard(),
                Fade(),
                PrayerOfMending(),
                PsychicScream(),
                PowerWordShield(),
                Renew(),
                LeapOfFaith(),
                
                // Talents
                VoidTendrils(),
                Psyfiend(),
                Phantasm(),
                DesperatePrayer(),
                SpectralGuise()

                );
        }

        #region Ability Composites

        private static Composite HandlePotionOfTheJadeSerpent()
        {
            /*
                On Heroism/BL/TW
                On Cooldown
                On Dark Soul
             */
            return new Decorator(ret => Settings.UsePotion,
                new PrioritySelector(
                    Item.UseBagItem(76093, ret => Settings.PotionCondition == 0 && !Me.HasAura("Potion of the Jade Serpent") && Hasted, "PotJS -> Heroism/Bloodlust/Time Warp"),
                    Item.UseBagItem(76093, ret => Settings.PotionCondition == 1 && !Me.HasAura("Potion of the Jade Serpent"), "PotJS -> On Cooldown"),
                    Item.UseBagItem(76093, ret => Settings.PotionCondition == 0 && !Me.HasAura("Potion of the Jade Serpent") && Me.HasAnyAura("Dark Soul: Knowledge", "Dark Soul: Misery", "Dark Soul: Instability"), "PotJS -> Dark Soul")
                    ));
        }
        
        private static Composite HandleUseHealthstones()
        {
            return new PrioritySelector(
                Item.UseBagItem(5512, ret => Settings.UseHealthstones && Me.Combat && Me.HealthPercent < Settings.HealthstoneHPPercent && !Settings.OnlyHealthstoneWithDarkRegen, "HP Low"),
                Item.UseBagItem(5512, ret => Settings.UseHealthstones && Me.Combat && Settings.OnlyHealthstoneWithDarkRegen && Me.HasAura("Dark Regeneration"), "Dark Regeneration Active")
                );
        }

        private static Composite HandleEngineerGloves()
        {
            return new PrioritySelector(
                /* Synapse Springs
                    0 = Never
                    1 = On Boss Or Player
                    2 = On Cooldown
                */
                new Decorator(
                    ret => Settings.UseSynapseSprings
                        && ((Settings.SynapseSpringsCond == 1 && Me.CurrentTarget.IsBossOrPlayer()) ||
                            (Settings.SynapseSpringsCond == 2)),
                Item.UseEngineerGloves())

                );
        }

        private static Composite HandleLifeblood()
        {
            return new Decorator(ret => Settings.UseLifeblood,
                new PrioritySelector(
                     /* 
                     0 = On Low HP
                     1 = On Boss Or Player
                     2 = On Cooldown
                     */
                    Spell.Cast("Lifeblood", ret => Settings.LifebloodCond == 0 && Me.HealthPercent <= Settings.LifebloodLowHPValue),
                    Spell.Cast("Lifeblood", ret => Settings.LifebloodCond == 1 && Me.CurrentTarget.IsBossOrPlayer()),
                    Spell.Cast("Lifeblood", ret => Settings.LifebloodCond == 2)
                ));
        }

        
        private static Composite Fade()
        {
            return new PrioritySelector(
                Spell.CastSelf("Fade", ret => Settings.UseFadeToReduceThreat && (Me.CurrentTarget.ThreatInfo.RawPercent > 90 || Targeting.GetAggroOnMeWithin(Me.Location, 40) >= 1))
                );
        }

        
        public static Composite FearWard()
        {
            return new Decorator(ret => Settings.UseFearWard,
                Spell.CastSelf("Fear Ward", ret => !Me.HasAura("Fear Ward"))
                );
        }

        
        private static Composite PrayerOfMending()
        {
            return new PrioritySelector(
                Spell.CastSelf("Prayer of Mending", ret => Settings.UsePoMLowHP && Me.HealthPercent < Settings.PoMLowHPValue),
                Spell.CastSelf("Prayer of Mending", ret => Settings.AlwaysKeepPoMActive && !CachedUnits.CachedPartyMembers.Any(u => u != null && u.IsValid && u.HasMyAura("Prayer Of Mending")))
                );
        }

        private static Composite PsychicScream()
        {
            return new PrioritySelector(
                Spell.CastSelf("Psychic Scream", ret => Settings.PsychicScreamTarget && Me.CurrentTarget != null && Me.CurrentTarget.Distance < 8),
                Spell.CastSelf("Psychic Scream", ret => Settings.PsychicScreamAny && Unit.CachedNearbyAttackableUnits(Me.Location, 8).Any(u => u != null && u.IsValid && !u.IsPet))
                );
        }

        private static Composite PowerWordShield()
        {
            return new PrioritySelector(
                Spell.CastSelf("Power Word: Shield", ret => Settings.UsePowerWordShieldLowHp && Me.HealthPercent < Settings.PowerWordShieldLowHPValue && !Me.HasAura("Weakened Soul"))
                );
        }

        private static Composite Renew()
        {
            return new PrioritySelector(
                Spell.CastSelf("Renew", ret => Settings.UseRenewLowHp && !Me.HasMyAura("Renew") && Me.HealthPercent < Settings.RenewLowHPValue)
                );
        }

        private static Composite LeapOfFaith()
        {
            return new PrioritySelector(
                Spell.Cast("Leap of Faith", on => _leapOfFaithUnit, ret => _leapOfFaithUnit != null)
                );
        }

        #endregion

        #region Talent Composites

        private static Composite VoidTendrils()
        {
            return new PrioritySelector(
                Spell.Cast("Void Tendrils", ret => Settings.UseVoidTendrilsOnTargetInRange && Me.CurrentTarget.Distance <= 8)
                );
        }

        private static Composite Psyfiend()
        {
            return new PrioritySelector(
                    Spell.CastOnGround("Psyfiend", on => Me.CurrentTarget.Location,
                        ret => TalentManager.HasTalent(2) && Settings.PsyfiendOnCooldown && Me.CurrentTarget.Distance < 25, true)
                );

        }

        private static Composite Phantasm()
        {
            return new PrioritySelector(
                Spell.Cast("Fade", ret => TalentManager.HasTalent(6) && Settings.FadeWhenSnaredRooted && Me.IsRooted())
                );
        }

        private static Composite DesperatePrayer()
        {
            return new PrioritySelector(
                Spell.Cast("Desperate Prayer", ret => TalentManager.HasTalent(10) && Settings.UseDesperatePrayer && Me.HealthPercent < Settings.DesperatePrayerHealthValue)
                );
        }
        
        private static Composite SpectralGuise()
        {
            return new Decorator(ret => TalentManager.HasTalent(11) && !Me.HasAnyAura("Alliance Flag", "Horde Flag", "Netherstorm Flag", "Orb of Power"),
                new PrioritySelector(
                    Spell.Cast("Spectral Guise", ret => Settings.SpectralGuiseOnLowHP && Me.HealthPercent < Settings.SpectralGuiseLowHPValue)
                ));
        }



        #endregion Talent Composites


        #region Conditions

        public static bool Hasted { get { return StyxWoW.Me.HasAnyAura("Bloodlust", "Heroism", "Ancient Hysteria", "Time Warp", "Drums of Rage"); } }

        #endregion Conditions

        #region Counts / Vars

        public static WoWUnit _leapOfFaithUnit;

        private static int _angelicFeatherCharges;

        public static int _nearbyAoEUnitCount;

        public static Composite SetCounts
        {
            get
            {
                return new Action(delegate
                {
                    try
                    {
                        if (Me.CurrentTarget != null)
                        {
                            var countList = Unit.CachedNearbyAttackableUnits(Me.CurrentTarget.Location, 11);
                            _nearbyAoEUnitCount = countList != null ? countList.Count(u => u != null && !u.IsDead && !u.IsTotem()) : 0;
                            
                            if (Settings.LeapOfFaithLowHP)
                            {
                                _leapOfFaithUnit = CachedUnits.CachedPartyMembers.FirstOrDefault(
                                    u => u != null && u.IsValid &&

                                        u.Distance < 40 && u.Distance > 20 &&
                                        u.HealthPercent < Settings.LeapOfFaithLowHPValue &&
                                        Me.IsFacing(u) &&
                                        u.InLineOfSpellSight

                                    );
                            }

                            if (Settings.LeapOfFaithCrowdControl && _leapOfFaithUnit == null)
                            {
                                _leapOfFaithUnit = CachedUnits.CachedPartyMembers.FirstOrDefault(
                                    u => u != null && u.IsValid &&

                                        u.Distance < 40 && u.Distance > 20 &&
                                        u.IsCrowdControlled() &&
                                        Me.IsFacing(u) &&
                                        u.InLineOfSpellSight

                                    );
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Debug("Unit detection failed with: {0}", ex);
                        _nearbyAoEUnitCount = 0;
                    }
                    return RunStatus.Failure;
                });
            }
        }
        #endregion

        }
}
